/*
 * Copyright (C) 2020 Baidu, Inc. All Rights Reserved.
 */
package cn.xiaoxige.plugin.transform

import com.android.build.api.transform.DirectoryInput
import com.android.build.api.transform.Format
import com.android.build.api.transform.JarInput
import com.android.build.api.transform.QualifiedContent
import com.android.build.api.transform.Transform
import com.android.build.api.transform.TransformException
import com.android.build.api.transform.TransformInvocation
import com.android.build.api.transform.TransformOutputProvider
import com.android.build.gradle.internal.pipeline.TransformManager
import com.android.utils.FileUtils
import org.apache.commons.codec.digest.DigestUtils
import org.gradle.api.Project
import org.objectweb.asm.ClassReader
import org.objectweb.asm.ClassVisitor
import org.objectweb.asm.ClassWriter

class PrintTransform extends Transform {

    final static def NAME = 'PrintTransform'

    private def mProject

    PrintTransform(Project project) {
        this.mProject = project
    }

    @Override
    String getName() {
        return NAME
    }

    @Override
    Set<QualifiedContent.ContentType> getInputTypes() {
        return TransformManager.CONTENT_CLASS
    }

    @Override
    Set<? super QualifiedContent.Scope> getScopes() {
        return TransformManager.SCOPE_FULL_PROJECT
    }

    @Override
    boolean isIncremental() {
        return false
    }

    @Override
    void transform(TransformInvocation transformInvocation) throws TransformException, InterruptedException, IOException {
        super.transform(transformInvocation)

        def inputs = transformInvocation.inputs
        def outputProvider = transformInvocation.outputProvider

        println("output: ${outputProvider.toString()}")
        inputs.forEach { input ->
            println('----------- jar -------------')
            input.jarInputs.forEach { jar ->
                println("jar: name = ${jar.name}, status = ${jar.status}")
                handleJar(jar, outputProvider)
            }
            println('-----------------------------')
            println('----------- dir -------------')
            input.directoryInputs.forEach { dir ->
                println("dir: name = ${dir.name}, file.path = ${dir.file.absolutePath}")
                handleDir(dir, outputProvider)
            }
            println('-----------------------------')
        }
    }

    void handleJar(JarInput jar, TransformOutputProvider outputProvider) {
        def jarName = jar.name
        def md5Name = DigestUtils.md5Hex(jar.file.absolutePath)
        if (jarName.endsWith('.jar')) {
            jarName = jarName.substring(0, jarName.length() - 4)
        }

        def file = outputProvider.getContentLocation(
                "$md5Name$jarName",
                jar.contentTypes,
                jar.scopes,
                Format.JAR
        )

        FileUtils.copyFile(jar.file, file)
    }

    void handleDir(DirectoryInput dir, TransformOutputProvider outputProvider) {

        dir.file.eachFileRecurse { file ->
            println(file.name)
            if (file.name.endsWith('Activity.class')) {
                ClassReader classReader = new ClassReader(file.bytes)
                ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_MAXS)
                ClassVisitor classVisitor = new LifecycleClassVisitor(classWriter)
                classReader.accept(classVisitor, ClassReader.EXPAND_FRAMES)

                // 新的 bytes
                byte[] bytes = classWriter.toByteArray()
                // 重新写入文件
                FileOutputStream os = new FileOutputStream(file.absolutePath)
                os.write(bytes)
                os.close()
            }
        }

        def file = outputProvider.getContentLocation(
                dir.name,
                dir.contentTypes,
                dir.scopes,
                Format.DIRECTORY
        )
        FileUtils.copyDirectory(dir.file, file)
    }
}